package com.tc.bean;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @Auther: tianchao
 * @Date: 2021/10/26 15:16
 * @Description:
 */
@Slf4j
public class JacksonEnumDeserializer extends JsonDeserializer<IEnum<?>> implements ContextualDeserializer {

    private Class<?> clazz;
    @Override
    public IEnum<?> deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        Class<?> enumType = clazz;
        if (!Enum.class.isAssignableFrom(clazz)){
            //throw new IllegalArgumentException("IENUM 实现类必须是一个枚举类");
            log.info("IENUM 实现类必须是一个枚举类");
            return null;
        }
        if (Objects.isNull(enumType) || !enumType.isEnum()) {
            return null;
        }
        String text = jsonParser.getText();
        Method method = StringToEnumConverterFactory.getMethod(enumType);
        Enum<? extends IEnum>[] enumConstants = (Enum<? extends IEnum>[]) enumType.getEnumConstants();
        // 将值与枚举对象对应并缓存
        for (Enum<? extends IEnum> e : enumConstants) {
            try {
                if (Objects.equals(method.invoke(e).toString(), text)) {
                    return (IEnum<?>) e;
                }
            } catch (IllegalAccessException | InvocationTargetException ex) {
                log.error("获取枚举值错误!!! ", ex);
            }
        }
        return null;
    }

    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
        Class<?> rawCls = ctxt.getContextualType().getRawClass();
        JacksonEnumDeserializer converter = new JacksonEnumDeserializer();
        converter.setClazz(rawCls);
        return converter;
    }

    private void setClazz(Class<?> rawCls) {
        this.clazz = rawCls;
    }
}
